import { Service, Context } from 'egg';
const Crawler = require("crawler");

export class PagesService extends Service {
    private crawler = new Crawler({
        rateLimit: 2000,
        // 在每个请求处理完毕后将调用此回调函数
        callback : async (error, res, done) => {
            const { ctx, app } = this;
            const model = app.model;
            if(error){
                await model.Pages.update({
                    error_message: String(error),
                    status: 'error',
                },
                {
                    where: {
                        id: res.options.id
                    }
                });
            }else{
                const $ = res.$;
                const links = $('.l-name-h3 > a');
                links.each(async function (index) {
                    try {
                        await model.transaction(async transaction => {
                            await model.Pages.update({
                                status: 'success',
                            }, {
                                where: {
                                    id: res.options.id
                                },
                                transaction,
                            });
                            await model.Lists.create({
                                url: links.eq(index).attr('href'),
                                status: 'waiting',
                                page_id: res.options.id,
                            }, {
                                transaction,
                            });
                        });
                    } catch (err) {
                        ctx.throw(500, err.message);
                    }
                });
            }
            done();
        }
    });

    constructor (ctx: Context) {
        super(ctx);
        this.crawler.on('drain', function () {
            console.log('======== finished ========');
        })
    }
    
    public async start() {
        const { app } = this;
        const { model } = app;
        const pages = await model.Pages.findAll({
            where: {
                status: [ 'error', 'waiting' ]
            },
            attributes: [ 'id', 'url' ]
        });
        const queue: Array<any> = [];
        for (let i = 0; i < pages.length; i++) {
            const page = pages[i].get({
                plain: true,
            });
            queue.push({
                uri: page.url,
                id: page.id,
            });
        }
        this.crawler.queue(queue);

        return {
            status: 0,
            msg: 'success',
            data: pages
        }
    }
}

export default PagesService;
